/*********************************************************************************
 *      Copyright:  (C) 2025 LingYun<lingyun@email.com>
 *                  All rights reserved.
 *
 *       Filename:  socket_sever.c
 *    Description:  This file 
 *                 
 *        Version:  1.0.0(13/03/25)
 *         Author:  LingYun <lingyun@email.com>
 *      ChangeLog:  1, Release initial version on "13/03/25 16:06:50"
 *                 
 ********************************************************************************/
#include "socket_server.h"

int socket_server(char *listen_ip,int listen_port)
{
	int                       sockfd;
	int                       on=1;
	struct  sockaddr_in       servaddr;
	int                       rv=0;

	sockfd=socket(AF_INET,SOCK_STREAM,0);
	if(sockfd<0)
	{
		dbg_print("Creat socket failure: %s\n",strerror(errno));
		return -1;
	}
	dbg_print("Create socket[%d] successfully!\n",sockfd);
	setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));

	memset(&servaddr,0,sizeof(servaddr));
	servaddr.sin_family=AF_INET;
	servaddr.sin_port=htons(listen_port);

	if(!listen_ip)   /*没有传IP*/
	{
		servaddr.sin_addr.s_addr=htonl(INADDR_ANY);    /*服务器会监听所有可用网络接口(INADDR_ANY)*/
	}
	else     /*传了IP*/
	{
		if(inet_pton(AF_INET,listen_ip,&servaddr.sin_addr) <= 0)  /*把传进来的IP地址十进制转成二进制，*/
		{
			dbg_print("inet_pton() set listen IP address failure\n");
			rv=-2;
			goto CleanUp;
		}
	}

	if((rv = bind(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr))) < 0)
	{
		dbg_print("Socket[%d] bind on port[%d] failure:%s\n", sockfd, listen_port, strerror(errno));
		rv=-3;
		goto CleanUp;
	}

	if(listen(sockfd,128)<0)
	{
		dbg_print("listen port failure:%s\n",strerror(errno));
		rv=-4;
		goto CleanUp;
	}


CleanUp:
	if(rv<0)
		close(sockfd);
	else
		rv = sockfd;

	return rv;

}


void socket_rlimit(void)
{
	struct rlimit limit = {0};
	getrlimit(RLIMIT_NOFILE, &limit );
	limit.rlim_cur = limit.rlim_max;
	setrlimit(RLIMIT_NOFILE, &limit );
	dbg_print("Set socket open fd max count to %ld\n", limit.rlim_max);
}

/**/
int parse_data(uint8_t *buf, data_t *data)
{
	int         k = 0;
	char        *str = NULL;
	float       temp;

	if( !buf || !data )
	{
		log_warn("arguments is NULL");
		return -1;
	}

	str = strtok(buf, "=");
	while ( str )
	{   
		str = strtok(NULL, "\n");
		if ( k == 0 )
		{
			snprintf(data->sn, sizeof(data->sn), "%s", str);
		}
		else if ( k == 1 )
		{
			snprintf(data->time, sizeof(data->time), "%s", str);
		}
		else if ( k == 2)
		{

			temp = atof(str);
			snprintf(data->temper, sizeof(data->temper), "%.4f", temp);
		}
		++k;
		str = strtok(NULL, "=");
	}

	k = 0;
	return 0;
}

/**/
int parse_data_json(uint8_t *buf, data_t *data)
{
	int			k = 0;
	char		*str = NULL;
	float       temp;

	if( !buf || !data )
	{
		log_warn("arguments is NULL");
		return -1;
	}

	str = strtok(buf, ":");
	while ( str )
	{
		str = strtok(NULL, "\"");
		if ( k == 0 )   
		{               
			snprintf(data->sn, sizeof(data->sn), "%s", str);
		}               
		else if (k == 1 )
		{               
			snprintf(data->time, sizeof(data->time), "%s", str);
		}               
		else if (k == 2)
		{ 
			temp = atof(str);
			snprintf(data->temper, sizeof(data->temper), "%.4f", temp);
		}
		++k;
		str = strtok(NULL, ":");
	}

	k = 0;
	return 0;
}

/**/
int parse_data_tlv(uint8_t *buf, data_t *data) 
{
	char        *str = NULL;
	char 		temp_str[32];
	int			temperature = 1;
	uint16_t    crc_ch;
	char        id[10] = {0};

	if( !buf || !data )
	{
		log_warn("arguments is NULL");
		return -1;
	}


	uint16_t header = ntohs(*(uint16_t *)buf);
	if ( header != 0xFEDD )
	{
		log_error("Header failure\n");
		return -1;
	}

	uint8_t tag = buf[2];
	if ( tag != temperature )
	{
		log_error("Tag failure\n");
		return -1;
	}

	uint16_t length = (*(uint16_t *)(buf + 3));

	memcpy(id, buf + 5, 10);

	uint8_t year = buf[15];     		//年 - 2000
	uint8_t month = buf[16];    		//月
	uint8_t day = buf[17];      		//日
	uint8_t hour = buf[18];     		//时
	uint8_t minute = buf[19];   		//分
	uint8_t second = buf[20];   		//秒

	uint8_t temp_int = buf[21];         /*整数部分*/
	uint8_t temp_decimal1 = buf[22]; /*小数部分 ×10000*/
	uint8_t temp_decimal2 = buf[23]; /*小数部分 ×10000*/

	/*CRC校验*/
	uint16_t crc = ntohs(*(uint16_t *)(buf + 24));
	crc_ch = crc_check(buf, length+5);
	
	if ( crc != crc_ch )
	{
		log_error("CRC failure\nCRC16: 0x%04X\nCRC16_check: 0x%04X\n", crc, crc_check);
		return -1;
	}

	strncpy(data->sn, id, sizeof(data->sn));
	snprintf(data->time, sizeof(data->time), 
			"%04d%02d%02d %02d:%02d:%02d",year + 2000, month, day, hour, minute, second);
	snprintf(data->temper, sizeof(data->temper), "%d.%02d%02d", temp_int, temp_decimal1, temp_decimal2);

	return 0;
}

static uint16_t crc_check(const uint8_t *data, size_t length)
{
	uint16_t          crc = 0xFFFF;
	size_t            i, j;

	for (i=0; i<length; i++)
	{
		crc ^= ((uint16_t)data[i] << 8);

		for(j=0; j<8; j++)
		{
			if (crc & 0x8000)
			{
				crc = (crc << 1) ^ CRC16_ITU_T_POLY;
			}
			else
			{
				crc <<= 1;
			}
		}
	}

	return crc;
}

